home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 19 / CU Amiga Magazine's Super CD-ROM 19 (1998)(EMAP Images)(GB)[!][issue 1998-02].iso / CUCD / Programming / LEDA / source / src / arith / ikarat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-16  |  5.7 KB  |  238 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA  3.1c
  4. +
  5. +
  6. +  ikarat.c
  7. +
  8. +
  9. +  Copyright (c) 1994  by  Max-Planck-Institut fuer Informatik
  10. +  Im Stadtwald, 6600 Saarbruecken, FRG     
  11. +  All rights reserved.
  12. *******************************************************************************/
  13.  
  14.  
  15. #include <LEDA/impl/iint.h>
  16. #include <LEDA/impl/iloc.h>
  17.  
  18. #ifndef KARATSUBA_LIMIT2
  19. #define KARATSUBA_LIMIT2 15
  20. #endif
  21.  
  22. /* Formulae:
  23.     a == B^n a1 + a0;
  24.     b == B^n b1 + b0;
  25.     a b == (B^(2n) + B^n) a1 b1 + B^n (a1 - a0) (b0 - b1) + (B^n + 1) a0 b0;
  26.  
  27.     -----------------
  28. V    |     a1 b1     |
  29.     -----------------
  30.         -----------------
  31. IV        |     a1 b1    |
  32.         -----------------
  33.         -----------------
  34. III        ||a1-a0||b0-b1|    |
  35.         -----------------
  36.         -----------------
  37. II        |     a0 b0    |
  38.         -----------------
  39.             -----------------
  40. I            |     a0 b0    |
  41.             -----------------
  42.     ---------------------------------
  43.     |        prod        |
  44.     ---------------------------------
  45.  
  46.         |    |    |    |
  47.         n3    n2    n    0
  48.  
  49. */
  50.  
  51.  
  52. static  PLACE vecsub (/*diff, a, b, k*/);
  53. static  PLACE vecadd4carry (/*sum, a, b, c, d, carry, k*/);
  54. static  int vecadd3subcarry (/*accu, a, b, c, d, carry, k*/);
  55. static  PLACE vecaddPLACE (/*accu, a, d, k*/);
  56. static  PLACE vecaddscarry (/*accu, a, d, k*/);
  57.  
  58. void karatsuba_mult (prod, a, b, tmp, n2)
  59.     PLACE *prod, *a, *b, *tmp;
  60.     int n2;
  61.  
  62. /*     In:    a[n2], b[n2];    n2 == 2^k * n0, with n0 <= KARATSUBA_LIMIT2
  63.     Out:    prod[2*n2] = a[n2] * b[n2];
  64.     Local:    tmp[2*n2] for intermediate results
  65.     for n2>KARATSUBA_LIMIT2:    karatsuba-recursion with k-1
  66.     else:        standard multiplication
  67. */
  68. {    int sign, i, n, n3;
  69.     PLACE carry;
  70.     int subcarry;
  71.  
  72.     if (n2<=KARATSUBA_LIMIT2) {
  73.         /* use vecmuladd */
  74.         for ( i = 0; i < n2; i++)
  75.                 prod[i] = 0;
  76.             for ( i = 0; i < n2; i++) 
  77.                 prod[i+n2] = vecmuladd(&prod[i], a, b[i], n2);
  78.         return;
  79.     }
  80.  
  81.     n=n2/2;
  82.     n3=n2+n;
  83.  
  84.     karatsuba_mult(&prod[n2], a, b, prod, n);
  85.     /* prod:    |    a0*b0    |        |    */
  86.  
  87.     if (vecgt(a, &a[n], n)) {
  88.         sign=1;
  89.         vecsub(tmp, a, &a[n], n);    /* a0 - a1 */
  90.     } else {
  91.         sign=0;
  92.         vecsub(tmp, &a[n], a, n);    /* a1 - a0 */
  93.     }
  94.     /* tmp:        |    |    |    ||a0-a1||    */
  95.     if (vecgt(&b[n], b, n)) {
  96.         sign^=1;
  97.         vecsub(&tmp[n], &b[n], b, n);    /* b1 - b0 */
  98.     } else {
  99.         vecsub(&tmp[n], b, &b[n], n);    /* b0 - b1 */
  100.     }
  101.     /* tmp:        |    |    ||b1-b0|||a0-a1||    */
  102.  
  103.  
  104.     karatsuba_mult(&tmp[n2], tmp, &tmp[n], prod, n);
  105.     /* tmp:        ||b1-b0|*|a0-a1|||b1-b0|||a0-a1||    */
  106.  
  107.     karatsuba_mult(tmp, &a[n], &b[n], prod, n);
  108.     /* tmp:        ||b1-b0|*|a0-a1||    a1*b1    |    */
  109.  
  110.     /*
  111.             ---------------------------------
  112.     prod        |     a0 b0    |        |
  113.             ---------------------------------
  114.  
  115.             ---------------------------------
  116.     tmp        ||a1-a0||b0-b1|    |     a1 b1    |
  117.             ---------------------------------
  118.     */
  119.  
  120.     if (sign==0) {        /* Einfach addieren */
  121.         for (i=0; i<n; i++)
  122.         prod[i]=prod[n2+i];            /* I */
  123.         /* I + II + III + IV */
  124.         carry=vecadd4carry(&prod[n], 
  125.             &prod[n3], &prod[n2], &tmp[n2], tmp, 0, n);
  126.         /* carry + II + III + IV + V */
  127.         carry=vecadd4carry(&prod[n2], 
  128.             &prod[n3], &tmp[n3], &tmp[n], tmp, carry, n);
  129.         /* carry + V */
  130.         vecaddPLACE(&prod[n3], &tmp[n], carry, n);
  131.     } else {        /* III subtrahieren */
  132.         for (i=0; i<n; i++)
  133.         prod[i]=prod[n2+i];            /* I */
  134.         /* I + II + IV - III */
  135.         subcarry=vecadd3subcarry(&prod[n], 
  136.             &prod[n3], &prod[n2], tmp, &tmp[n2], 0, n);
  137.         /* carry + II + IV + V - III */
  138.         subcarry=vecadd3subcarry(&prod[n2], 
  139.             &prod[n3], &tmp[n], tmp, &tmp[n3], subcarry, n);
  140.         /* subcarry + V */
  141.         vecaddscarry (&prod[n3], &tmp[n], subcarry, n);
  142.     }
  143. }
  144.  
  145. static  PLACE vecsub (diff, a, b, k)
  146.         register PLACE *diff, *a, *b; 
  147.         register int k;
  148.         /* diff[k]=a[k]-b[k]; return carry (0 oder 1) */
  149. {       register PLACE carry=0;
  150.         for ( ; k>0; k--)
  151.         carry=PLACEsub(*a++, *b++, carry, diff++);
  152.         return (carry & 1);
  153. }
  154.  
  155. static  PLACE vecadd4carry (accu, a, b, c, d, carry, k)
  156.     PLACE *accu, *a, *b, *c, *d, carry;
  157.     int k;
  158.     /* accu[k]=a[k]+b[k]+c[k]+d[k]+carry; return carry; */
  159. {    PLACE ac, bc, cc, dc;
  160.     int i;
  161.     if (k==0)
  162.         return;
  163.     ac=PLACEadd(carry, *a, 0, accu);
  164.     bc=PLACEadd(*accu, *b, 0, accu);
  165.     cc=PLACEadd(*accu, *c, 0, accu);
  166.     dc=PLACEadd(*accu, *d, 0, accu);
  167.     for (i=1; i<k; i++) {
  168.         ac=PLACEadd(a[i], b[i], ac, &accu[i]);
  169.         bc=PLACEadd(accu[i], c[i], bc, &accu[i]);
  170.         cc=PLACEadd(accu[i], d[i], cc, &accu[i]);
  171.         dc=PLACEadd(accu[i], 0, dc, &accu[i]);
  172.     }
  173.     return ac+bc+cc+dc;
  174. }
  175.  
  176.  
  177. static  int vecadd3subcarry (accu, a, b, c, d, carry, k)
  178.     PLACE *accu, *a, *b, *c, *d;
  179.     int carry, k;
  180.     /* carry >= -1 */
  181.     /* accu[k]=a[k]+b[k]+c[k]-d[k]+carry; return carry; */
  182. {    PLACE ac=0, bc=0, cc=0, subc=0;
  183.     int i;
  184.     if (k==0)
  185.         return;
  186.     if (carry >= 0) {
  187.         ac = PLACEadd(carry, *a, 0, accu);
  188.         bc = PLACEadd(*accu, *b, 0, accu);
  189.         cc = PLACEadd(*accu, *c, 0, accu);
  190.         subc = PLACEsub(*accu, *d, 0, accu);
  191.     } else {
  192.         ac = 0;
  193.         bc = PLACEadd(*a, *b, 0, accu);
  194.         cc = PLACEadd(*accu, *c, 0, accu);
  195.         subc = PLACEsub(*accu, *d, 1, accu);
  196.     }
  197.     for (i=1; i<k; i++) {
  198.         ac=PLACEadd(a[i], b[i], ac, &accu[i]);
  199.         bc=PLACEadd(accu[i], c[i], bc, &accu[i]);
  200.         cc=PLACEadd(accu[i], 0, cc, &accu[i]);
  201.         subc=PLACEsub(accu[i], d[i], subc, &accu[i]);
  202.     }
  203.     return ac+bc+cc-subc;
  204. }
  205.  
  206. static  PLACE vecaddPLACE (accu, a, d, k)
  207.     PLACE *accu, *a, d;
  208.     int k;
  209.     /* accu[k]=a[k]+d; return carry; */
  210. {    PLACE carry=d;
  211.     for ( ; k>0; k-- )
  212.         carry=PLACEadd(*a++, carry, 0, accu++);
  213.     return carry;
  214. }
  215. /* ACHTUNG:    k==0  ==>  carry==d */
  216.  
  217. static  PLACE vecaddscarry (accu, a, scarry, k)
  218.     PLACE *accu, *a;
  219.     int scarry, k;
  220.     /* RADIX > scarry>=-1 */
  221.     /* accu[k]=a[k]+scarry; return carry; */
  222. {    PLACE carry;
  223.     if (scarry >= 0) {
  224.         carry = scarry;
  225.         for ( ; k>0; k-- )
  226.             carry=PLACEadd(*a++, carry, 0, accu++);
  227.         return carry;
  228.     } else {
  229.         carry = 1;
  230.         for ( ; k>0; k-- )
  231.             carry=PLACEsub(*a++, 0, carry, accu++);
  232.         return carry;
  233.     }
  234. }
  235. /* ACHTUNG:    k==0  ==>  carry==d */
  236.  
  237.